<?php
###############   COPYLEFT GPLv3 LICENSE   ###############
##
## JFX Version 0.2.7
## Website Management Software
## www.jfxcms.com
##
## Copyright 2009 GPLv3 - http://www.opensource.org/licenses/gpl-3.0.html
##
## Anthony Gallon
## oi_antz@hotmail.com
##
## Permission is hereby granted to any person having a copy of this software
## to freely use and modify as required so long as the copyright notices
## and branding remain intact.
##
## Full license details available at http://www.jfxcms.com/license
##
###############   COPYLEFT GPLv3 LICENSE   ###############

class JFX_Module {

    public $ThrowConfigExceptions = false;
    public $langCache = array();
    public $stylesheets = array();
    public $version = '0.2.3';
    public $dependencies = array();
    public $publicUrl = '';
    public $adminUrl = '';
    public $imageUrl = '';
    public $cssUrl = '';
    public $jsUrl = '';
    public $dirname = '';
    public $showCssLicense = true;
    public $showJsLicense = true;
    public $ownerLicense = '###############   COPYLEFT GPLv3 LICENSE   ###############
##
## JFX Version 0.2.7
## Website Management Software
## www.jfxcms.com
##
## Copyright 2009 GPLv3 - http://www.opensource.org/licenses/gpl-3.0.html
##
## Anthony Gallon
## oi_antz@hotmail.com
##
## Permission is hereby granted to any person having a copy of this software
## to freely use and modify as required so long as the copyright notices
## and branding remain intact.
##
## Full license details available at http://www.jfxcms.com/license
##
###############   COPYLEFT GPLv3 LICENSE   ###############';

    public $publicLicense = '###############   COPYLEFT GPLv3 LICENSE   ###############
##
## JFX Version 0.2.7
## Website Management Software
## www.jfxcms.com
##
## Copyrights 2009 GPLv3 - http://www.opensource.org/licenses/gpl-3.0.html
##
## Full license details available at http://www.jfxcms.com/license
##
###############   COPYLEFT GPLv3 LICENSE   ###############';






    public function __construct(){
        $CONFIG = JFX::registry('config');
        $this->adminUrl = $CONFIG->adminUrl.'/modules/admin/'.$this->keyname;
        $this->publicUrl = $CONFIG->baseUrl.$CONFIG->moduleServerFolder.'/'.$this->keyname;
        $this->cssUrl = $CONFIG->baseUrl.$CONFIG->moduleCssFolder.'/'.$this->keyname;
        $this->jsUrl = $CONFIG->baseUrl.$CONFIG->moduleJsFolder.'/'.$this->keyname;
        $this->imageUrl = $CONFIG->baseUrl.$CONFIG->moduleImageFolder.'/'.$this->keyname;
        $this->dirname = $CONFIG->modulesDir.'/'.$this->keyname;
        $this->loadConfig();

    }

    function loadConfig(){
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');

        // make sure this module is configurable!
        $num = $DB->fetchRow("SHOW TABLE STATUS LIKE '{$CONFIG->dbprefix}{$this->keyname}_config'");
        if(!is_array($num) || count($num)==0){
            return;
        }

        $config = $DB->fetchAll("SELECT * FROM {$CONFIG->dbprefix}{$this->keyname}_config");

        if($config === false) return;

        $varname = $this->keyname.'_config';
        $this->$varname = array();

        foreach($config as $k=>$v){
            $varname2 = $varname.'["'.$v['k'].'"]';
            eval('$this->'.$varname2.' = \''.$v['v'].'\';');
        }

    }

    function GetConfig($k){
        $varname = $this->keyname.'_config';
        $var = $this->$varname;
        if(array_key_exists($k, $var)) return $var[$k];
        else if($this->ThrowConfigExceptions) throw new Exception($this->GetName().'->GetConfig was asked to find a non-existing key: '.$k);
        else return false;
    }
    public function useCache(){
        return false;
    }

    public function getBlockActions(){
        return array();
    }

    public function getToolbarButtons(){
        return array();
    }

    public function getBlockButtons($blockDetails){
        return array();
    }

    public function getPageButtons($pageid){
        return array();
    }

    public function hook($name, &$params){
        $VIEW = JFX::registry('JFX_View');
        $SMARTY = JFX::registry('Smarty');
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        $USER = JFX::registry('JFX_User');
        $CRYPT = JFX::registry('JFX_Crypt');
        $LINK = JFX::registry('JFX_Link');
        $THEME = JFX::registry('JFX_Theme');
        $CORE = JFX::registry('JFX_Core');
        $SETTINGS = JFX::registry('JFX_Settings');
        
        $name = str_replace('..', '', $name);
        if(file_exists($this->dirname.'/hooks/'.$name.'.php')) include($this->dirname.'/hooks/'.$name.'.php');
    }


    public function createPermission($keyname){
        $CONFIG = JFX::registry('config');
        $DB = JFX::registry('db');
        $dbParams = array(
            'module_key' => $this->keyname,
            'keyname' => $keyname,
        );
        $DB->insert($CONFIG->dbprefix.'admin_permissions', $dbParams);
    }

    public function getDependencies(){
        return $this->dependencies;
    }

    public function getVersion(){
        return $this->version;
    }

    public function removePermission($keyname){
        $CONFIG = JFX::registry('config');
        $DB = JFX::registry('db');
        $DB->delete($CONFIG->dbprefix.'admin_permissions', "module_key = '{$this->keyname}' AND keyname = '{$keyname}'");
    }

    public function checkPermission($keyname){
        $USER = JFX::registry('JFX_User');
        return $USER->checkAdminPermission($this->keyname, $keyname);
    }

    public function printCssFile($filename){
        $CONFIG = JFX::registry('config');

        $fileParts = explode(',', $filename);

        if(count($fileParts)>1){
            foreach($fileParts as $filename){
                $this->printCssFile($filename);
            }
            return;
        }
        
        if(file_exists($this->dirname.'/css/'.$filename) &&
            is_readable($this->dirname.'/css/'.$filename)){

            $fc = file_get_contents($this->dirname.'/css/'.$filename);
            $fc = str_replace($this->ownerLicense, '', $fc);
            $fc = str_replace('/**/', '', $fc);
            $fc = str_replace(':|imgUrl|:', $this->imageUrl, $fc);
            echo "\n/*############################\n{$filename}\n*/\n";
            echo $fc;
        }

    }


    public function getIcon(){
        if(is_dir($this->dirname.'/images')){
            if(file_exists($this->dirname.'/images/icon.png')) return $this->imageUrl.'/icon.png';
            if(file_exists($this->dirname.'/images/icon.gif')) return $this->imageUrl.'/icon.gif';
            if(file_exists($this->dirname.'/images/icon.jpg')) return $this->imageUrl.'/icon.jpg';
        }
    }

    public function printJsFile($filename){
        $VIEW = JFX::registry('JFX_View');
        $SMARTY = JFX::registry('Smarty');
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        $USER = JFX::registry('JFX_User');
        $CRYPT = JFX::registry('JFX_Crypt');
        $LINK = JFX::registry('JFX_Link');
        $THEME = JFX::registry('JFX_Theme');
        $CORE = JFX::registry('JFX_Core');
        $SETTINGS = JFX::registry('JFX_Settings');

        $fileParts = explode(',', $filename);
        
        if(count($fileParts)>1){
            foreach($fileParts as $filename){
                $this->printJsFile($filename);
            }
            return;
        }

        if(file_exists($this->dirname.'/js/'.$filename) &&
            is_readable($this->dirname.'/js/'.$filename)){

            $finfo = pathinfo($this->dirname.'/js/'.$filename);
            if(strtolower($finfo['extension'])=='php'){
                while(ob_get_level()>0) ob_end_clean();
                echo '/*'.$this->publicLicense.'*/'."\n\n";
                include($this->dirname.'/js/'.$filename);
                exit;
            }

            $fc = file_get_contents($this->dirname.'/js/'.$filename);
            $fc = str_replace($this->ownerLicense, '', $fc);
            $fc = str_replace('/**/', '', $fc);
            echo "\n/*############################\n{$filename}\n*/\n";
            echo $fc;
        }
    }

    public function getExpiresHeader($secs){
        $tstamp = time()+(int)$secs;
        $retVal = 'Expires: '.
            date('D', $tstamp).', '.date('j', $tstamp).' '.date('M', $tstamp).' '.
            date('Y', $tstamp).' '.date('P', $tstamp).' '.date('T', $tstamp);
        return $retVal;
    }

    public function printImage($filename){
        $CONFIG = JFX::registry('config');
        $filename = str_replace('../', '', $filename);
        $headers = array(
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'gif' => 'image/gif',
            'png' => 'image/png'
        );
        if(file_exists($this->dirname.'/images/'.$filename)){
            $pathinfo = pathinfo($this->dirname.'/images/'.$filename);
            if(!array_key_exists(strtolower($pathinfo['extension']), $headers)) exit;
            while(ob_get_level()>0) ob_end_clean();
            
            header('Content-type: '.$headers[strtolower($pathinfo['extension'])]);
            readfile($this->dirname.'/images/'.$filename);
            exit;
        }
    }

    public function fetchTemplate($filename){
        $CONFIG = JFX::registry('config');
        $SMARTY = JFX::registry('Smarty');
        $dirname = $CONFIG->modulesDir.'/'.$this->keyname.'/templates';
        return $SMARTY->fetch($dirname.'/'.$filename);
    }

    public function addStyleSheet($filename, $media='all'){
        $VIEW = JFX::registry('JFX_View');
        $CONFIG = JFX::registry('config');
        $VIEW->addCssLink($CONFIG->baseUrl.$CONFIG->moduleCssFolder.'/'.$this->keyname.'/'.$filename, $media);
    }

    public function addJsLink($filename){
        $VIEW = JFX::registry('JFX_View');
        $CONFIG = JFX::registry('config');
        $VIEW->addJsLink($CONFIG->baseUrl.$CONFIG->moduleJsFolder.'/'.$this->keyname.'/'.$filename);
    }

    public function removeStyleSheet($filename){
        if(array_key_exists($filename, $this->stylesheets)) unset($this->stylesheets[$filename]);
    }

    public function registerBlock($methodName, $title){
        if(!method_exists($methodName, $this)) return;
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        if($DB->countRows($CONFIG->dbprefix.'module_mapper', "module_key = '{$this->keyname}' AND method_name = '{$methodName}'")>0) return;
        $dbParams = array(
            'module_key' => $this->keyname,
            'method_name' => $methodName
        );
        $DB->insert($CONFIG->dbprefix.'module_mapper', $dbParams);
        $this->updateLang('module_mapper_'.$methodName, $title, '*');
    }

    public function setBlockId($id){
        $this->blockId = $id;
    }

    public function delete(){
        return 'You must override this method!';
    }



    public function getDefaultDetails($action){
        $details = array(
            'id' => $this->keyname,
            'parent_id' => '',
            'module_key' => $this->keyname,
            'sorting' => '',
            'page_parent' => '',
            'ajax_enabled' => '',
            'page_id' => '',
            'exec_order' => '',
            'class_name' => 'big-block'
        );
        return $details;
    }

    public function serve(){
        
    }

    public function getUninstallPreMessage(){
        $msg = $this->lang('uninstall_pre_message');
        if(trim($msg) == ''){
            $CORE = JFX::registry('JFX_Core');
            $msg = $CORE->getUninstallPreMessage();
        }
        return $msg;
    }

    public function getInstallPreMessage(){
        $msg = $this->lang('install_pre_message');
        if(trim($msg) == ''){
            $CORE = JFX::registry('JFX_Core');
            $msg = $CORE->getInstallPreMessage();
        }
        return $msg;
    }


    public function resetLanguages(){
        $DB = JFX::registry('db');
        $LANG = JFX::registry('lang');
        $CONFIG = JFX::registry('config');
        if(!is_dir($CONFIG->modulesDir.'/'.$this->keyname.'/lang')) return false;
        $langDir = $CONFIG->modulesDir.'/'.$this->keyname.'/lang';
        $installedLangs = $DB->fetchAll("SELECT * FROM {$CONFIG->dbprefix}languages");
        foreach($installedLangs as $language){
            if(file_exists($langDir.'/'.$language['keyname'].'.php')){
                require($langDir.'/'.$language['keyname'].'.php');
                if(is_array($lang)){
                    foreach($lang as $label => $value){
                        //echo $label.' '.$value.'<br />';
                        $LANG->update($this->keyname, $label, $value, $language['keyname'], '*');
                    }
                }
                if(isset($contentLang) && is_array($contentLang)){
                    foreach($contentLang as $k=>$v){
                        $LANG->updateContent($this->keyname, $v['label'], $v['id'], $v['value'], $language['keyname'], '*');
                    }
                }
            }else if(file_exists($langDir.'/en_US.php')){
                require($langDir.'/en_US.php');
                if(is_array($lang)){
                    foreach($lang as $label => $value){
                        $LANG->update($this->keyname, $label, $value, $language['keyname']);
                    }
                }
                if(isset($contentLang) && is_array($contentLang)){
                    foreach($contentLang as $k=>$v){
                        $LANG->updateContent($this->keyname, $v['label'], $v['id'], $v['value'], $language['keyname'], '*');
                    }
                }
            }
        }
        return true;
    }

    public function copyToNewBlock(){
        
    }

    public function deleteLanguages(){
        $DB = JFX::registry('db');
        $LANG = JFX::registry('lang');
        $DB->delete($CONFIG->dbprefix.'lang_system', "module_key = '{$this->keyname}'");
    }

    public function loadLang($lang=''){
        $USER = JFX::registry('JFX_User');
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        if($lang == ''){
            $lang = $USER->lang;
        };
        $lang = $DB->escape($lang);
        $langs = $DB->fetchAll("SELECT label, v FROM {$CONFIG->dbprefix}lang_system WHERE module_key = '{$moduleKey}' AND lang = '{$lang}'");

        $lang = array();
        foreach($langs as $k=>$v){
            $lang[$v['label']] = $v['v'];
        };
        $this->langCache = array_merge($this->langCache, $lang);
        return $lang;
    }

    public function prepare(){
        
    }

    public function lang($label, $lang=''){
        $LANG = JFX::registry('lang');
        return $LANG->get($this->keyname, $label, $lang);
    }

    public function updateLang($label, $value, $lang=''){
        $LANG = JFX::registry('lang');
        return $LANG->update($this->keyname, $label, $value, $lang);
    }

    public function deleteLang($label, $lang='*', $workspaceid=''){
        $LANG = JFX::registry('lang');
        return $LANG->delete($this->keyname, $label, $lang, $workspaceid);
    }

    public function getContentLang($label, $id, $lang='', $workspaceid=''){
        $LANG = JFX::registry('lang');
        return $LANG->getContent($this->keyname, $label, $id, $lang, $workspaceid);
    }

    public function updateContentLang($label, $id, $value, $lang='', $workspaceid=''){
        $LANG = JFX::registry('lang');
       // echo __FILE__.__LINE__.$value.'<br />';
        return $LANG->updateContent($this->keyname, $label, $id, $value, $lang, $workspaceid);
    }

    public function deleteContentLang($label, $id, $lang='*', $workspaceid=''){
        $LANG = JFX::registry('lang');
        return $LANG->deleteContent($this->keyname, $label, $id, $lang, $workspaceid);
    }

    public function getDetails($action){
        $details = $this->getDefaultDetails($action);
        $details['default_content'] = $this->getDefaultContent($action);
        return JFX::arrayToObject($details);
    }

    public function getDefaultContent($action){
        return 'This is the default content for module of type '.$this->title;
    }

    public function getTitle(){
        return $this->title;
    }

    public function getContent($id){
        return 'You need to override the method "getContent" in your module. This is the main method that gets called when a block instance is rendered.';
    }

    public function getInstalledModules(){
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        $modules = array();
        $installedModules = $DB->fetchAll("SELECT * FROM {$CONFIG->dbprefix}modules ORDER BY sorting ASC");
        foreach($installedModules as $k=>$v){
            $modules[$k] = $v;
            $modules[$k]['object'] = JFX::registry('JFX_Module_'.ucfirst(strtolower($v['keyname'])));
        }
        return $modules;
    }

    public static function getInstance($moduleKey){
        $module = JFX::registry('JFX_Module_'.ucfirst(strtolower($moduleKey)));
        if(!is_object($module)){
            $module = JFX_Module::newInstance($moduleKey);
            JFX::register('JFX_Module_'.ucfirst(strtolower($moduleKey)), $module);
            return $module;
        }else{
            return $module;
        }
    }



    /**
     * Will return a new object of type $moduleKey, if it can't, it will return false
     * @param string $moduleKey
     * @return object JFX_Module_.$moduleKey
     */
    public static function newInstance($moduleKey){
        if(!JFX_Module::isValidModule($moduleKey)) return false;
        $className = 'JFX_Module_'.ucfirst($moduleKey);
        if(class_exists($className, false)) return new $className;
        else return false;
    }


    /**
     * Will try to locate the module class. If the class exists will return true else will return false
     * @global JFXConfig $CONFIG
     * @param string $moduleKey
     * @return bool $bool
     */
    public static function isValidModule($moduleKey){
        $CONFIG = JFX::registry('config');
        $moduleKey = strtolower($moduleKey);
        $moduleKey = preg_replace('/[^a-z0-9]/', '', $moduleKey);
        if(is_dir($CONFIG->modulesDir.'/'.$moduleKey) && file_exists($CONFIG->modulesDir.'/'.$moduleKey.'/'.$moduleKey.'.module.php')){
            require_once($CONFIG->modulesDir.'/'.$moduleKey.'/'.$moduleKey.'.module.php');
            if(class_exists('JFX_Module_'.ucfirst($moduleKey))) return true;
            else echo 'File found but not the class contained!';
        }else{
            //throw new exception('not directory: '.$CONFIG->modulesDir.'/'.$moduleKey.' or not file: '.$CONFIG->modulesDir.'/'.$moduleKey.'/'.$moduleKey.'.module.php');
            return false;

        }
        return false;
    }

    public static function isValidAction($moduleKey, $action){
        if(!JFX_Module::isValidModule($moduleKey)) return false;
        $moduleObj = JFX::registry('JFX_Module_'.$moduleKey);
        $actions = $moduleObj->getBlockActions();
        foreach($actions as $k=>$v){
            if($v['keyname'] == $action) return true;
        }
        return false;
    }

    public function copy($action, $oldBlockid, $newBlockid, $oldPageid, $newPageid, $oldWorkspaceid, $newWorkspaceid){
        
    }

    public static function isInstalled($moduleKey){
        $DB = JFX::registry('db');
        $CONFIG = JFX::registry('config');
        $moduleKey = preg_replace('/[^a-zA-Z0-9]/', '', $moduleKey);
        //$DB->debug(true);
        return (bool) $DB->countRows($CONFIG->dbprefix.'modules', "keyname = '{$moduleKey}'");
    }

    public function updateSettings(){
        JFX::addError('Please override the method "updateSettings" in your module class file');
    }

    public function install(){
        $this->resetLanguages();
    }

    public function uninstall(){
        
    }


    public function saveExport($filename){
        if(file_exists($filename)) unlink($filename);
        $MM = JFX::registry('JFX_Module_Manager');
        $MM->export($this->keyname, $filename);
    }


}